import EventDispatch from "./EventDispatcher";

//websocket封装class方法
class WebsocketClient extends EventDispatch{
    //构造函数
    constructor({
        url,
        maxReconnectAttempts=5,//最大重连次数
        reconnectInterval=10000,//重试连接延迟时间
        heartbeatInterval=1000*72,//心跳检测间隔时间
        maxHeartbreatAttempts=5,//心跳检测重试次数
        sendHeartbreatTxt="ping",
        resHeartbreatTxt="pang",
    }){
        super();
        //websocket连接地址
        this.url = url;
        //websocket连接对象
        this.socket = null;
        this.timeoutId = null;
        this.timeout = 5000;
        //重连次数设置
        this.reconnectAttempts = 0;
        //最大重连次数设置
        this.maxReconnectAttempts = maxReconnectAttempts;
        //重连间隔时间 10s时间
        this.reconnectInterval = reconnectInterval;
        //心跳机制跳动的时间间隔，需要服务端判断，72秒
        this.heartbeatInterval = heartbeatInterval;
        //心跳检测机制的状态信息控制
        this.heartAttempts = 0;
        this.maxHeartbreatAttempts = maxHeartbreatAttempts;
        this.isHeartbeatRes = null;
        //心跳包关键字
        this.sendHeartbreatTxt = sendHeartbreatTxt;
        this.resHeartbreatTxt = resHeartbreatTxt;
        //心跳检测机制时间计时器对象
        this.heartbeatTimer = null;
        //是否终止websocket
        this.stopWs = false;
        
    }

    //定义websocket生命周期钩子函数，方便原生方法的调用
    onopen(callback){
        this.addEventListener("open",callback);//绑定事件
    }

    onmessage(callback){
        this.addEventListener("message",callback);
    }

    onclose(callback){
        this.addEventListener("close",callback);
    }
    //错误回调
    onerror(callback){
        this.addEventListener("error",callback);
    }

    //发送消息的方法
    send(message){
        if(this.socket && this.socket.readyState == WebSocket.OPEN){
            this.socket.send(message);//发送消息的方法，发送对应的消息
        }else{
            console.error("[websocket]未连接");
        }
    }

    //初始化连接的方法
    connect(){
        if(!("WebSocket" in window)){
            console.error("浏览器不支持websocket");
            return ;
        }
        if(this.reconnectAttempts === 0){
            console.log("初始化连接中....");
        }
        //判断是否已经连接过，如果连接上，退出
        if(this.socket && this.socket.readyState == WebSocket.OPEN){
            return;
        }

        //开启连接服务
        this.socket = new WebSocket(this.url);
        
        this.timeoutId = setTimeout(()=>{
            //超过一定时间没有打开
            if(this.socket && this.socket.readyState == WebSocket.OPEN){
                this.handleConnect();//重连机制循环调用，主要是针对网络慢的情况
            }
        },this.timeout);

        //打开连接消息的方法
        this.socket.onopen=(event)=>{
            clearTimeout(this.timeoutId);
            this.stopWs = false;//关闭状态重置为false
            //一旦连接成功，那么就把尝试连接的次数初始化为0即可。
            this.reconnectAttempts = 0;
            //连接成功，尝试启动心跳检测
            this.startHeartbeat();//开启心跳检测
            console.log("websocket连接成功，等待服务端推送消息[onopen]...")
            this.dispatchEvent("open",event);//调度方法池中绑定的方法
        }
        //监听服务端消息的返回
        this.socket.onmessage = event=>{

            //如果心跳包服务端返回提醒一下，是心跳检测
            if(event.data == this.resHeartbreatTxt){
                console.log("心跳检测成功")
                // this.isHeartbeatRes = true;
            }

            this.dispatchEvent("message",event);
            // console.log("接受服务端传递过来的消息",event.data);
        }

        //关闭连接请求
        this.socket.onclose = (event)=>{
            clearTimeout(this.timeoutId);
            if(this.reconnectAttempts===0){
                console.log("websocket关闭连接请求,[onclose]....");
            }
            //尝试重连，连接关闭，尝试重新连接，如果是人为的手动关闭，那么就不尝试重连服务
            if(!this.stopWs){
                this.handleConnect();
            }
            this.dispatchEvent("close",event);
        }

        //连接错误信息
        this.socket.onerror = (event)=>{
            clearTimeout(this.timeoutId);
            if(this.reconnectAttempts === 0){
                console.error("websocket连接错误,[onerror]...");
            }
            //连接失败尝试重连
            this.handleConnect();
            this.closeHeartbeat();//关闭心跳检测方法
            this.dispatchEvent("error",event);
        }
    }

    //封装断网重连的方法
    handleConnect(){
        //小于最大重连次数
        if(this.reconnectAttempts < this.maxReconnectAttempts){
            this.reconnectAttempts++;//次数+1
            console.log(`尝试重连(${this.reconnectAttempts}/${this.maxReconnectAttempts})`)
            setTimeout(()=>{
                this.connect();//连接方法
            },this.reconnectInterval*this.reconnectAttempts);
        }else{
            console.error("最大重连失败，终止尝试重连",this.url);
            this.close();//关闭连接
            return ;
        }
    }

    //开始心跳检测定时的发送心跳信息
    startHeartbeat(){
        //手动关闭了直接返回，无需发送心跳
        if(this.stopWs) {
            this.closeHeartbeat();
            return ;
        }
        if(this.heartbeatTimer) this.closeHeartbeat();//关闭心跳，如果当前有心跳状态的话
        this.heartbeatTimer = setInterval(()=>{
            this.heartAttempts++;
            if(this.socket){
                //超过最大连接次数的效果
                // if(this.heartAttempts>this.maxHeartbreatAttempts){
                //     console.log("尝试心跳连接次数超限，关闭重连,关闭连接，请手动尝试重连")
                //     this.closeHeartbeat();//关闭心跳机制，尝试重连
                //     this.close();
                //     this.connect();//重联信息
                //     return ;
                // }
                // console.log(this.isHeartbeatRes);
                // //服务端心跳包没有给响应,初始化的数据设置为null,初始化不考虑，暂时先不做限制了
                // if(this.isHeartbeatRes === false){
                //     this.heartAttempts++;
                //     this.closeHeartbeat();//如果没有响应直接退出
                // }else if(this.isHeartbeatRes === true){
                //     //连接成功，就把尝试次数还原0
                //     this.heartAttempts = 0;//初始化尝试的次数
                // }
                
                this.socket.send(this.sendHeartbreatTxt)
                console.log("发送心跳包数据...."+this.heartAttempts);
                // this.isHeartbeatRes = false;//发送完消息以后就会变成false
            }else{
                console.log("[websocket]未连接，不尝试心跳推送");
            }
        },this.heartbeatInterval);
    }

    //关闭心跳检测
    closeHeartbeat(){
        clearInterval(this.heartbeatTimer);
        this.heartbeatTimer = null;
    }

    //关闭连接的方法
    close(){
        //如果有状态，关闭状态
        if(this.socket){
            this.stopWs = true;//关闭状态
            this.socket.close();
            this.socket = null;
        }
        //关闭心跳推送
        this.closeHeartbeat();
    }
}

export default WebsocketClient;
